package com.chang.search.thread;

import java.util.concurrent.*;

/**
 * @author: changzhenxi
 * @date: 2024年11月05日 10:07
 * @Version: 1.0
 * @description:
 */
public class ThreadTest {


    public static ExecutorService executor = Executors.newFixedThreadPool(10);

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        System.out.println("开始执行线程");
//        threadTest01 threadTest01 = new threadTest01();
//        threadTest01.start();
//        System.out.println(threadTest01.isAlive());
        //FutureTask<Integer> futureTask = new FutureTask<>(new threadTest03());
        // 等待整个线程执行完成，获取返回结果
        //new Thread(futureTask).start();
        // 阻塞等待整个线程执行完毕，获取返回结果
        //Integer aaa = futureTask.get();

        //线程池七大参数:ThreadPoolExecutor(
        // int corePoolSize,  核心线程数[一直存活不会被释放], 创建时准备就绪的线程数量,等待接受异步任务执行
        // int maximumPoolSize, 允许的最大线程数量 控制资源
        // long keepAliveTime, 存活时间 线程空闲超过指定时间就会被释放
        // TimeUnit unit,    时间单位
        // BlockingQueue<Runnable> workQueue, 阻塞队列 如果任务有很多,就会将目前多的任务放在队列里面,只要有线程空闲,就会去队列里面取出新的任务执行
        // ThreadFactory threadFactory, 线程的创建工厂
        // RejectedExecutionHandler handler) 如果连阻塞队列都满了 就按照指定的拒绝策略去执行拒绝任务
        //
        /* 面试场景题: 一个线程池 core 7, max 20, queue 50,  100个并发线程进来该怎么分配
         7个核心线程会立即执行,然后接下来50个任务会进入队列,然后再开20-7=13个线程进行执行(max-core),剩下的30个任务使用拒绝策略 (有一个拒绝策略是直接用同步阻塞式进行执行)
         并且如果7个核心线程执行完之后 新开的线程会被13个任务在阻塞队列前面插队执行
        * */

        /*   线程池工作顺序
        //   1,线程池创建,准备好core数量的核心线程,准备接受任务
               如果核心线程满了,就会将接下来的任务放到阻塞队列中,空闲的core线程会自己去阻塞队列获取任务执行
               如果阻塞队列都满了,就直接开新的线程执行,最大只能开到max指定的数量
               如果max数量内也满了 就用RejectedExecutionHandler拒绝策略
               如果max数量内的执行完成了 有很多空闲,接下来就会在指定的keepAliveTime存活时间以后 释放max数量内不含core数量的线程
        * */
        //        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(5,
        //                200,
        //                10,
        //                TimeUnit.SECONDS,
        //                new LinkedBlockingDeque<>(100000), //阻塞队列大小默认是Integer的最大值.如果使用默认的就会爆内存.所以一定要传入业务定制的数量 这个数量可以是做压力测试之后得到系统峰值的数量
        //                Executors.defaultThreadFactory(), // 默认线程工厂
        //                new ThreadPoolExecutor.AbortPolicy()); // 该丢弃策略代表直接把最新的直接丢掉

//        CompletableFuture<Void> completableFuture = CompletableFuture.runAsync(() -> {
//            System.out.println("当前线程" + Thread.currentThread().getId());
//        }, executor);

        /*CompletableFuture<Integer> completableFuture = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程" + Thread.currentThread().getId());
            return 777/0;
        }, executor)
                // 执行结束之后要做的事 虽然能得到异常信息,无法修改返回数据
                .whenComplete((res, ex) -> {System.out.println("异步任务执行结束后..结果为:" + res+"异常有:"+ex);})
                // 线程执行结束遇到异常时给一个默认返回值
                .exceptionally(throwable -> {return 10;});*/

        /*CompletableFuture<Integer> completableFuture = CompletableFuture.supplyAsync(() -> {
                    System.out.println("当前线程" + Thread.currentThread().getId());
                    return 777/4;
                }, executor)
                // 方法执行完之后的处理 (无论失败成功)
                .handle((res,thr)->{
                    if (res != null) {
                        return res*2;
                    }
                    if (thr != null) {
                        return 0;
                    }
                    return 999;
                });*/

        /* 线程串行化
            thenRunAsync 异步执行另一个方法不能获取到上一步的执行结果
             completableFuture.thenRunAsync(()-> {System.out.println("任务2启动了.....");},executor);
            thenAcceptAsync 异步执行上一步的返回结果
             completableFuture.thenAcceptAsync(result -> {System.out.println("result = " + result);});
        * */
        CompletableFuture<String> completableFuture = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程" + Thread.currentThread().getId());
            return 777;
        }, executor).thenApplyAsync(res -> {
            System.out.println("任务2启动了.....");
            return "hello" + res;
        }, executor);
        System.out.println(completableFuture.get()); // get方法为阻塞式方法
    }

    public static class threadTest01 extends Thread {
        @Override
        public void run() {
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            System.out.println("threadTest01");
        }
    }

    public static class threadTest02 implements Runnable {

        @Override
        public void run() {

        }
    }

    public static class threadTest03 implements Callable<Integer> {
        @Override
        public Integer call() {
            System.out.println("当前线程" + Thread.currentThread().getId());
            return 999;
        }
    }
}
